﻿#include "ReadO.h"// 包含自定义头文件，用于使用 ReadO 类来处理 Rinex O 文件
ReadO::ReadO() {
}

ReadO::ReadO(string filePath1)
{
    this->filePath = filePath1;
}

bool ReadO::set_file(string filePath1)
{
    this->filePath = filePath1;
    return true;
}
struct SOW {
    int week;
    int sec;
    double sesec;
};
struct CalendT {
    int year; int month; int day; int hour; int min; int sec;
    double sesec;
};
struct BaseT {
    time_t sec;
    double sesec;
};

class TimeSys
{
public:
    TimeSys() {
        originT = { 1970,01,01,0,0,0 };
    };
    ~TimeSys();
public:
    SOW calend2sow(CalendT t0);
    CalendT sow2calend(SOW t0);
    BaseT str2baseT(string t);
    bool compare(SOW t1, SOW t2);
    double time_minus(BaseT t1, BaseT t2);
    bool print_time(CalendT t);
    bool print_time(SOW t);

public:
    CalendT str2calendT(string t);
    BaseT sow2baseT(SOW t);
    SOW   baseT2sow(BaseT t);
    BaseT calend2baseT(CalendT t);
    CalendT baseT2calend(BaseT t);

protected:
    CalendT originT;
};

class GPSTime : public TimeSys
{
public:
    GPSTime() {
        originT = { 1980,01,06,0,0,0 };
    }
};

class BDSTime : public TimeSys
{
public:
    BDSTime() {
        originT = { 2006,01,01,0,0,0 };
    }
};
// 读取 Rinex O 文件的函数实现
bool ReadO::parse_file()
{
    ifstream file(this->filePath);    // 打开文件
    if (!file.is_open())        // 检查文件是否成功打开
    {
        cerr << "无法打开文件: " << this->filePath << endl;// 输出错误信息
        return false;
    }

    string line;
    bool inHeader = true;   // 标记是否在文件头部

    while (getline(file, line) && !file.eof()) // 逐行读取文件
    {
        if (inHeader)
        {
            head.push_back(line);// 将头部信息添加到 head 向量中
            if (line.find("END OF HEADER") != string::npos)// 检查是否到达头部结束标记 
            {
                inHeader = false;// 标记离开头部
            }
        }
        else
        {
            if (line[0] == '>') // 检查是否为新的历元开始
            {
                obsEpoch epoch;
                epoch.time = line.substr(2, 29);// 存储历元时间
                epoch.numSat = atoi(line.substr(34, 36).c_str());
                int i = 0;/* 计数多少个循环 */
                while (i < epoch.numSat && getline(file, line))// 读取该历元内的所有观测值 
                {
                    obsSat listObsSat;
                    istringstream iss(line);// 创建字符串流用于解析观测值
                    iss >> listObsSat.satID;// 读取卫星标识符
                    double value;
                    while (iss >> value) // 读取观测值
                    {
                        listObsSat.values.push_back(value);
                    }
                    epoch.listObsSat.push_back(listObsSat);// 将观测值添加到该历元的观测值向量中
                    if (i++ == epoch.numSat) continue;
                }
                ListObs.push_back(epoch);// 将该历元添加到Listobs 向量中
            }
        }
    }

    // 关闭文件
    file.close();
    return true;
}

vector<obsEpoch>* ReadO::get_obs()
{
    return &this->ListObs;
}

// 显示文件头部信息的函数实现
void ReadO::print_head()
{
    // 遍历 head 向量并输出每一行
    for (const auto& line : head)
        cout << line << endl;
}

// 修改函数名以反映可输出多个历元
void ReadO::print_body(int epochCount)
{
    int count = min(epochCount, static_cast<int>(ListObs.size()));// 取指定数量和实际历元数量的较小值
    for (int i = 0; i < count; ++i)     // 遍历指定数量的历元
    {
        cout << ListObs[i].time << endl; // 输出历元时间
        for (const auto& listObsSat : ListObs[i].listObsSat)  // 遍历该历元内的所有观测值 
        {
            // 卫星ID固定宽度
            cout << left << setw(3) << listObsSat.satID;
            // 设置固定小数格式
            cout << fixed << right;
            // 按列设置格式
            for (size_t j = 0; j < listObsSat.values.size(); ++j)
            {
                /* 肖凯：下面建立一个循环就可以了，参考24号作业 */
                // 伪距数据：14位宽，3位小数
                if (j % 4 == 0)
                {
                    cout << " " << setw(14) << setprecision(3) << listObsSat.values[j];
                }
                // 载波相位：14位宽，5位小数 
                else if (j % 4 == 1)
                {
                    cout << " " << setw(14) << setprecision(5) << listObsSat.values[j];
                }
                // 信噪比：8位宽，3位小数
                else if (j % 4 == 2)
                {
                    cout << " " << setw(8) << setprecision(3) << listObsSat.values[j];
                }
                // 多普勒：10位宽，3位小数
                else
                {
                    cout << " " << setw(10) << setprecision(3) << listObsSat.values[j];
                }
            }
            cout << endl;
        }
    }
}
